package controller;

import java.io.IOException;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Calendar;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import model.Measurement;
import model.Sensor;
import DAO.MeasurementsDao;
import DAO.SensorDao;
import database.DBManager;

/**
 * Servlet implementation class GraphServlet
 */
public class GraphServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	private DBManager myDb;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public GraphServlet() {
		super();
		// TODO Auto-generated constructor stub
	}

	public void init(ServletConfig servletconfig) {
		// Initialisatie
		myDb = (DBManager) servletconfig.getServletContext().getAttribute(
				"dbmanager");
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher view = null;
		if (!isLoggedIn(request)) {
			view = request.getRequestDispatcher("index.jsp");
		} else {
			Logger.createLog(request);
			MeasurementsDao md = new MeasurementsDao(myDb);
			view = request.getRequestDispatcher("WEB-INF/graphs.jsp");
			request.setAttribute("keerGedaan", 0);
			request.setAttribute("eersteKeer", "eersteKeer");
			// lijst met dagen setten
			request.setAttribute("dagenLijst", getTijden(dagenVerschil(request)));
			// lijst met verschil in dagen zetten
			request.setAttribute("dagenVerschil", dagenVerschil(request));
		}
		request = getWarningInfo(request);
		view.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher view = null;
		if (!isLoggedIn(request)) {
			view = request.getRequestDispatcher("index.jsp");
		} else {
			Logger.createLog(request);
			request.setAttribute("keerGedaan", 0);
			request.setAttribute("eersteKeer", "asd");
			MeasurementsDao md = new MeasurementsDao(myDb);
			view = request.getRequestDispatcher("WEB-INF/graphs.jsp");

			request.setAttribute("dagenVerschil", dagenVerschil(request));
			request.setAttribute("dagenLijst", getTijden(dagenVerschil(request)));
			if((Integer)request.getAttribute("dagenVerschil") != -1){
				request.setAttribute("temp", functie(md, request, 4));
				request.setAttribute("air", functie(md, request, 5));
				request.setAttribute("light", functie(md, request, 2));
				request.setAttribute("movement", functie(md, request, 1));
				request.setAttribute("door", functie(md, request, 3));
				request.setAttribute("lichtSterkte", functie(md, request, 6));
				setSession(request);
			}
		}
		request = getWarningInfo(request);
		view.forward(request, response);
	}

	public int hoursFromDate(Date date) {
		Calendar cal = Calendar.getInstance();
		int hours;
		cal.setTime(date);
		hours = cal.get(Calendar.HOUR_OF_DAY);
		return (hours + 1);
	}
	
	public int dayFromDate(Date date) {
		Calendar cal = Calendar.getInstance();
		int day;
		cal.setTime(date);
		day = cal.get(Calendar.DAY_OF_MONTH); 
		return day ;
	}

	public ArrayList<Measurement> getMeasurementsBetweenDates(int sensor,
			Date date, Date date2) {
		MeasurementsDao md = new MeasurementsDao(myDb);
		return md.getMeasurementsBetweenDates(sensor, date, date2);
	}

	public Measurement getMeasurementBefore(Date getDate, int getSensorID) {
		MeasurementsDao md = new MeasurementsDao(myDb);
		return md.getMeasurementBeforeDateWithID(getDate, getSensorID);
	}

	public int[][] functie(MeasurementsDao md, HttpServletRequest request, int sensorID) {
		ArrayList<Measurement> lijst = md.getMeasurementsBetweenDates(sensorID, toDate(request)[0], toDate(request)[1]);
		
		int dagenVerschil 	= (Integer) request.getAttribute("dagenVerschil");
		int[] dagen 		= getTijden(dagenVerschil(request));	
		int uurVerschil 	= 0;
		
		if(dagen.length != 1)
			uurVerschil = dagen[1];
		else
			uurVerschil = 24;
		
		int[][] waardes = new int[dagenVerschil][24 / uurVerschil];	
		
		Calendar calVan = Calendar.getInstance();
		Calendar calM = Calendar.getInstance();
		calVan.setTime(toDate(request)[0]);
		
		for (int i = 0; i < dagenVerschil; i++) {	
			
			for (int x = 0; x < (24 / uurVerschil); x++) {			
				int vanaf = x * uurVerschil;
				int tot = (x + 1) * uurVerschil;
				int teller = 0;
				int som = 0;
				if (lijst.size() != 0) {				
					for (Measurement m : lijst) {
						calM.setTime(m.getMeasureDate());
						if (hoursFromDate(m.getMeasureDate()) >= vanaf && hoursFromDate(m.getMeasureDate()) < tot && calVan.get(Calendar.DAY_OF_MONTH) == calM.get(Calendar.DAY_OF_MONTH)) {
							som += m.getValue();
							teller++;
						}
					}
				}
				if (teller != 0) {
					waardes[i][x] = (som / teller);
				} else if (i == 0 && x == 0) {
					waardes[i][x] = getLaatsteValue(request, sensorID);
				} else if (i == 0 && x != 0 || i != 0 && x != 0) {
					waardes[i][x] = waardes[i][x - 1];
				} else if (i != 0 && x == 0) {
					waardes[i][x] = waardes[i - 1][(24 / uurVerschil) - 1];
				}						
			}
			calVan.add(calVan.DAY_OF_MONTH, 1);
		}
		return waardes;
	}

	public int getLaatsteValue(HttpServletRequest request, int sensorID){
		String van = (String) request.getParameter("van");
		
		int jaar = (Integer.parseInt(van.substring(6, 10)) - 1900);
		int maand = (Integer.parseInt(van.substring(0, 2)) - 1);
		int d = Integer.parseInt(van.substring(3, 5));

		Date datumVan = new Date(jaar, maand, d);
		Measurement m = getMeasurementBefore(datumVan, sensorID);
		if(m != null){
			double dou = m.getValue();
			int i = (int)dou;
			return i;
		} else {
			return 0;
		}
	}
	
	public Date[] toDate(HttpServletRequest request) {
		Date[] date = new Date[2];

		String van = (String) request.getParameter("van");
		String tot = (String) request.getParameter("tot");

		int jaar = (Integer.parseInt(van.substring(6, 10)) - 1900);
		int maand = (Integer.parseInt(van.substring(0, 2)) - 1);
		int dag = Integer.parseInt(van.substring(3, 5));

		int jaar2 = (Integer.parseInt(tot.substring(6, 10)) - 1900);
		int maand2 = (Integer.parseInt(tot.substring(0, 2)) - 1);
		int dag2 = Integer.parseInt(tot.substring(3, 5));
		dag2 +=1;
		
		Date datumVan = new Date(jaar, maand, dag);
		Date datumTot = new Date(jaar2, maand2, dag2);

		date[0] = datumVan;
		date[1] = datumTot;
		return date;
	}

	public int dagenVerschil(HttpServletRequest request) {
		String van = (String) request.getParameter("van");
		String tot = (String) request.getParameter("tot");
		if (van != null || tot != null) {
			if (van.equals("") || tot.equals("") ) {
				return -1;
			} else {
				Calendar cal1 = Calendar.getInstance();
				Calendar cal2 = Calendar.getInstance();

				cal1.set(Integer.parseInt(van.substring(6, 10)),
						Integer.parseInt(van.substring(0, 2)),
						Integer.parseInt(van.substring(3, 5)));
				cal2.set(Integer.parseInt(tot.substring(6, 10)),
						Integer.parseInt(tot.substring(0, 2)),
						Integer.parseInt(tot.substring(3, 5)));
				long milis1 = cal1.getTimeInMillis();
				long milis2 = cal2.getTimeInMillis();
				long diff = milis2 - milis1;
				if (cal2.before(cal1)) {
					return -1;
				} else {
					long diffDays = diff / (24 * 60 * 60 * 1000);
					return (int) diffDays + 1;
				}
			}
		}
		return -1;
	}

	private void setSession(HttpServletRequest request) {
		HttpSession session = request.getSession();
		session.setAttribute("van", request.getParameter("van"));
		session.setAttribute("tot", request.getParameter("tot"));
		Cookie cookie = new Cookie("JSESSIONID", session.getId());
		cookie.setMaxAge(60 * 60 * 24 * 7);
	}

	private boolean isLoggedIn(HttpServletRequest request){
		HttpSession session = request.getSession();
		boolean loggedIn = false;
		if(session.getAttribute("logged") != null){
			if(session.getAttribute("logged").equals("true")){
				loggedIn = true;
			}
		}
		return loggedIn;
	}

	public int[] getTijden(int dagenVerschil) {
		if (dagenVerschil <= 1) {
			return new int[] { 24, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
					14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
		} else if (dagenVerschil <= 2) {
			return new int[] { 24, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22 };
		} else if (dagenVerschil <= 4) {
			return new int[] { 24, 4, 8, 12, 16, 20 };
		} else if (dagenVerschil <= 6) {
			return new int[] { 24, 6, 12, 18 };
		} else if (dagenVerschil <= 8) {
			return new int[] { 24, 8, 16 };
		} else if (dagenVerschil <= 12) {
			return new int[] { 24, 12 };
		}  else if (dagenVerschil <= 26) {
			return new int[] { 24 };
		} else if (dagenVerschil > 24) {
			return new int[] { 0 };
		} 
		return null;
	}
	
	private HttpServletRequest getWarningInfo(HttpServletRequest request) {
		MeasurementsDao md = new MeasurementsDao(myDb);
		ArrayList<Measurement> latestMeasurements = new ArrayList<Measurement>();
		for (int i = 1; i <= 5; i++) {
			Measurement measurement = md.getLatestMeasurementByID(i);
			if (measurement != null) {
				latestMeasurements.add(measurement);
			}
		}
		SensorDao sdao = new SensorDao(myDb);
		ArrayList<Sensor> sensors = sdao.getSensors();
		request.setAttribute("sensorsmax", sensors);
		request.setAttribute("latestMeasurements", latestMeasurements);
		return request;
	}
}
